package ${pknDAO}.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;

import com.fly.common.PaginationSupport;
import com.fly.core.BaseDAO;
import ${packageName}.dao.${className}DAO;
import ${pknEntity}.${className};

/**
 * 
 * ${className}DAO 接口实现类
 * 
 * @author 00fly
 * @version [版本号, ${date?date}]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */

@SuppressWarnings("unchecked")
@Repository
public class ${className}DAOImpl extends BaseDAO<${className}> implements ${className}DAO
{
    
    /**
     * <默认构造函数>
     */
    public ${className}DAOImpl()
    {
        super();
    }
    
    /**
     * 构造whereClause
     * 
     * @param criteria
     * @return
     */
    private String buildWhereClause(${className} criteria)
    {
        if (criteria == null)
        {
            return "";
        }
        StringBuilder whereClause = new StringBuilder();
        if (criteria.${pk.getMethod}() != null)
        {
            whereClause.append(" and ${pk.name}=?");
        }
        <#list columns as column>
        if (criteria.${column.getMethod}() != null)
        {
            whereClause.append(" and ${column.name}=?");
        }
        </#list> 
        if (whereClause.length() > 4)
        {
            return whereClause.substring(4);
        }
        return "";
    }
    
    /**
     * 构造whereParams
     * 
     * @param criteria
     * @return
     * 
     */
    private List<Object> buildWhereParams(${className} criteria)
    {
        if (criteria == null)
        {
            return Collections.emptyList();
        }
        List<Object> whereParams = new ArrayList<>();
        if (criteria.${pk.getMethod}() != null)
        {
            whereParams.add(criteria.${pk.getMethod}());
        }
        <#list columns as column>
        if (criteria.${column.getMethod}() != null)
        {
            whereParams.add(criteria.${column.getMethod}());
        }
        </#list> 
        return whereParams;
    }
    
    /**
     * 根据条件删除数据
     * 
     * @param criteria 条件对象
     * @return
     * 
     */
    @Override
    public int deleteByCriteria(${className} criteria)
    {
        StringBuilder sql = new StringBuilder("delete from ${tableName}");
        String whereClause = buildWhereClause(criteria);
        List<Object> whereParams = buildWhereParams(criteria);
        if (StringUtils.isNotEmpty(whereClause))
        {
            sql.append(" where ").append(whereClause);
        }
        return update(sql.toString(), whereParams.toArray());
    }
    
    /**
     * 根据主键id删除数据
     * 
     * @param id 主键
     * @return
     * 
     */
    @Override
    public int deleteById(${pk.javaType} id)
    {
        String sql = "delete from ${tableName} where ${pk.name}=?";
        return update(sql, id);
    }
    
    /**
     * 根据主键id列表删除数据
     * 
     * @param ids 主键列表
     * @return
     * 
     */
    @Override
    public int deleteById(${pk.javaType}[] ids)
    {
        ${pk.javaType}[][] idsArr = new ${pk.javaType}[ids.length][1];
        for (int i = 0; i < ids.length; i++)
        {
            idsArr[i][0] = ids[i];
        }
        String sql = "delete from ${tableName} where ${pk.name}=?";
        return batch(sql, idsArr).length;
    }
    
    /**
     * 根据主键id列表删除数据
     * 
     * @param ids 主键列表
     * @return
     * 
     */
    @Override
    public int deleteById(List<${pk.javaType}> ids)
    {
        ${pk.javaType}[][] idsArr = new ${pk.javaType}[ids.size()][1];
        for (int i = 0; i < ids.size(); i++)
        {
            idsArr[i][0] = ids.get(i);
        }
        String sql = "delete from ${tableName} where ${pk.name}=?";
        return batch(sql, idsArr).length;
    }
    
    /**
     * 增加记录(插入全字段)
     * 
     * @param bean 待插入对象
     * @return
     * 
     */
    @Override
    public int insert(${className} bean)
    {
        String sql = "insert into ${tableName} (<#list columns as column>${column.name}<#if column_has_next>,</#if> </#list>) values(<#list columns as column>?<#if column_has_next>, </#if></#list>)";
        return update(sql,<#list columns as column> bean.${column.getMethod}()<#if column_has_next>,</#if></#list>);
    }
    
    /**
     * 增加记录(仅插入非空字段)
     * 
     * @param bean 待插入对象
     * @return
     * 
     */
    @Override
    public int insertSelective(${className} bean)
    {
        StringBuilder columns = new StringBuilder();
        StringBuilder values = new StringBuilder();
        List<Object> params = new ArrayList<>();
        <#list columns as column>
        if (bean.${column.getMethod}() != null)
        {
            columns.append(", ${column.name}");
            values.append(", ?");
            params.add(bean.${column.getMethod}());
        }
        </#list>
        StringBuilder sql = new StringBuilder("insert into ${tableName} (").append(columns.substring(1)).append(")");
        sql.append(" values(").append(values.substring(1)).append(")");
        return update(sql.toString(), params.toArray());
    }
    
    /**
     * 查询全部
     * 
     * @return
     * 
     */
    @Override
    public List<${className}> queryAll()
    {
        String sql = "select ${pk.name}<#list columns as column>, ${column.name}</#list> from ${tableName}";
        return query(${className}.class, sql);
    }
    
    /**
     * 根据条件查询
     * 
     * @param criteria 条件对象
     * @return
     * 
     */
    @Override
    public List<${className}> queryByCriteria(${className} criteria)
    {
        StringBuilder sql = new StringBuilder("select ${pk.name}<#list columns as column>, ${column.name}</#list> from ${tableName} ");
        String whereClause = buildWhereClause(criteria);
        List<Object> whereParams = buildWhereParams(criteria);
        if (StringUtils.isNotEmpty(whereClause))
        {
            sql.append(" where ").append(whereClause);
        }
        return query(${className}.class, sql.toString(), whereParams.toArray());
    }
    
    /**
     * 根据id查找数据
     * 
     * @param id 主键
     * @return
     * 
     */
    @Override
    public ${className} queryById(${pk.javaType} id)
    {
        String sql = "select ${pk.name}<#list columns as column>, ${column.name}</#list> from ${tableName} where ${pk.name}=?";
        return (${className})queryFirst(${className}.class, sql, id);
    }
    
    /**
     * 根据条件分页查询
     * 
     * @param criteria 条件对象
     * @param pageNo 页号
     * @param pageSize 页大小
     * @return
     * 
     */
    @Override
    public PaginationSupport<${className}> queryForPagination(${className} criteria, int pageNo, int pageSize)
    {
        StringBuilder sql = new StringBuilder("select ${pk.name}<#list columns as column>, ${column.name}</#list> from ${tableName}");
        String whereClause = buildWhereClause(criteria);
        List<Object> whereParams = buildWhereParams(criteria);
        if (StringUtils.isNotEmpty(whereClause))
        {
            sql.append(" where ").append(whereClause);
        }
        return queryForPagination(${className}.class, sql.toString(), pageNo, pageSize, whereParams.toArray());
    }
    
    /**
     * 根据条件查询数据条数
     * 
     * @param criteria 条件对象
     * @return
     * 
     */
    @Override
    public long queryTotal(${className} criteria)
    {
        StringBuilder sql = new StringBuilder("select count(1) from ${tableName}");
        String whereClause = buildWhereClause(criteria);
        List<Object> whereParams = buildWhereParams(criteria);
        if (StringUtils.isNotEmpty(whereClause))
        {
            sql.append(" where ").append(whereClause);
        }
        return queryForLong(sql.toString(), whereParams.toArray());
    }
    
    /**
     * 根据复杂条件更新全字段数据
     * 
     * @param bean 待更新对象
     * @param criteria 条件对象
     * @return
     * 
     */
    @Override
    public int updateByCriteria(${className} bean, ${className} criteria)
    {
        StringBuilder sql = new StringBuilder("update ${tableName} set <#list columns as column>${column.name}=?<#if column_has_next>, </#if></#list>");
        List<Object> params = new ArrayList<>();
        <#list columns as column>
        params.add(bean.${column.getMethod}());
        </#list>
        String whereClause = buildWhereClause(criteria);
        List<Object> whereParams = buildWhereParams(criteria);
        if (StringUtils.isNotEmpty(whereClause))
        {
            sql.append(" where ").append(whereClause);
        }
        params.addAll(whereParams);
        return update(sql.toString(), params.toArray());
    }
    
    /**
     * 根据复杂条件更新非空字段数据
     * 
     * @param bean 待更新对象
     * @param criteria 条件对象
     * @return
     * 
     */
    @Override
    public int updateByCriteriaSelective(${className} bean, ${className} criteria)
    {
        StringBuilder sql = new StringBuilder("update ${tableName} set");
        StringBuilder columns = new StringBuilder();
        List<Object> params = new ArrayList<>();
        <#list columns as column>
        if (bean.${column.getMethod}() != null)
        {
            columns.append(", ${column.name}=?");
            params.add(bean.${column.getMethod}());
        }
        </#list>
        sql.append(columns.substring(1));
        
        String whereClause = buildWhereClause(criteria);
        List<Object> whereParams = buildWhereParams(criteria);
        if (StringUtils.isNotEmpty(whereClause))
        {
            sql.append(" where ").append(whereClause);
        }
        params.addAll(whereParams);
        return update(sql.toString(), params.toArray());
    }
    
    /**
     * 根据id更新全部数据
     * 
     * @param bean 待更新对象
     * @return
     * 
     */
    @Override
    public int updateById(${className} bean)
    {
        String sql = "update ${tableName} set <#list columns as column>${column.name}=?<#if column_has_next>, </#if></#list> where ${pk.name}=?";
        return update(sql,
            <#list columns as column>bean.${column.getMethod}(),
            </#list>bean.${pk.getMethod}());
    }
    
    /**
     * 根据id更新非空字段数据
     * 
     * @param bean 待更新对象
     * @return
     * 
     */
    @Override
    public int updateByIdSelective(${className} bean)
    {
        StringBuilder sql = new StringBuilder("update ${tableName} set");
        StringBuilder columns = new StringBuilder();
        List<Object> params = new ArrayList<>();
        <#list columns as column>
        if (bean.${column.getMethod}() != null)
        {
            columns.append(", ${column.name}=?");
            params.add(bean.${column.getMethod}());
        }
        </#list>
        sql.append(columns.substring(1));
        sql.append(" where ${pk.name}=?");
        params.add(bean.${pk.getMethod}());
        return update(sql.toString(), params.toArray());
    }
    
}